////////////////////////////////////////////////////////////////////////////////
// Copyright 2006 CORE Solutions Limited
// All rights reserved.
// PROPRIETARY AND CONFIDENTIAL INFORMATION.
// Use is subject to license terms.
//
// FUNCTION ID      :   SimpleMaintMultiRow
// AUTHOR           :   Ric Yik 
// DATE CREATE      :   2006/01/11
// DESCRIPTION      :   a MAINTENANCE FORM file for the function, SimpleMaintMultiRow
//                  :   
//                  :   
//                  :   
//
// MODIFICATION HISTORY:
// DATE         AUTHOR          VERSION NO.         COMMENT
// -----------  --------------  ------------------  -------------------
// 2006/01/11   Ric Yik         1.0                 source is generated.
//
//
//
////////////////////////////////////////////////////////////////////////////////

package com.erp.common.web.multirow;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.erp.common.web.RemarkTextPopup;
import com.erp.framework.controller.form.SimpleMaintStyleForm;
import com.erp.framework.model.pk.SimpleBasePk;
import com.erp.framework.model.schema.TableSchema;
import com.erp.framework.util.logger.Logger;

/**
 * The base class for Maintenance Form to be used by SimpleMaintMultiRowAction
 * @author Ric YIK
 * 
 * @see com.erp.common.web.multirow.SimpleMaintMultiRowAction
 * @see com.erp.common.web.multirow.SimpleMaintMultiRowForm
 * @see com.erp.common.web.multirow.SimpleMaintMultiRow
 */
public abstract class SimpleMaintMultiRowForm extends SimpleMaintStyleForm {

    public SimpleMaintMultiRowForm() {
        super();
        this.setTs(this.makeTableSchema());
        this.setTsName(this.getTs().getClass().getName());
    }

    private boolean[] editingRow = new boolean[this.getChildRowClass().length];

    private int[] currentRowIdx = new int[this.getChildRowClass().length];

    private SimpleMaintMultiRow[] originalRow = new SimpleMaintMultiRow[this.getChildRowClass().length];

    public abstract TableSchema makeTableSchema();

    public abstract String getCompanyCode();

    public abstract void setCompanyCode(String companyCode);

    public abstract String getDcInd();

    public abstract void setDcInd(String dcInd);

    public abstract Class[] getChildRowClass();

    protected static interface MultiRowValidator {
        public void validateMultiRow(ActionErrors errors);
    }

    public void setPageModeAsCreate() {
        this.setPageMode("create");
    }

    public int getCurrentRowIdx() {
        return currentRowIdx[this.getFolderIdxAsIntInternal()];
    }

    public void setCurrentRowIdx(int currentRowIdx) {
        this.currentRowIdx[this.getFolderIdxAsIntInternal()] = currentRowIdx;
    }

    public boolean isEditingRow() {
        return editingRow[this.getFolderIdxAsIntInternal()];
    }

    public void setEditingRow(boolean editingRow) {
        this.editingRow[this.getFolderIdxAsIntInternal()] = editingRow;
    }

    protected SimpleMaintMultiRow makeMultiRow(int folderIdxInternal) {
        try {
            return (SimpleMaintMultiRow) this.getChildRowClass()[folderIdxInternal].newInstance();
        } catch (InstantiationException e) {
            Logger.error(e);
            throw new RuntimeException(e.getMessage());
        } catch (IllegalAccessException e) {
            Logger.error(e);
            throw new RuntimeException(e.getMessage());
        }
    }

    public int getPageEventSrcAsInt() {
        try {
            return Integer.parseInt(this.getPageEventSrc());
        } catch (NumberFormatException e) {
            Logger.error(e);
            return -1;
        }
    }

    public void setPageEventSrcAsInt(int eventSrc) {
        this.setPageEventSrc(String.valueOf(eventSrc));
    }

    public int getFolderIdxAsInt() {
        return Integer.parseInt(this.getFolderIdx());
    }

    public int getFolderIdxAsIntInternal() {
        return this.getFolderIdxAsInt() - 1;
    }

    /**
     * Returns the current SimpleMaintMultiRow
     * 
     * Preconditions: this.getFolderIdxAsInternal() and this.getPageEventSrcAsInt() are valid.
     * @return the current SimpleMaintMultiRow
     */
    public SimpleMaintMultiRow getCurrentRow() {
        return this.getSimpleMaintMultiRows(this.getFolderIdxAsIntInternal()).getMultiRow(this.getCurrentRowIdx());
    }

    public abstract SimpleMaintMultiRowList getSimpleMaintMultiRows(final int folderIdx);

    public ActionForward startAddingRow(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, ActionForward forward) {
        ActionForward lastForward = this.finishEditingRow(mapping, formIn, request, response, errors, forward);
        if (errors.size() == 0) {
            final int folderIdxInternal = this.getFolderIdxAsIntInternal();
            SimpleMaintMultiRow creatingRow = this.makeMultiRow(folderIdxInternal);
            creatingRow.setTs(this.getCurrentChildTs());
            creatingRow.setRowModeCreating();
            this.setCurrIdx(folderIdxInternal);
            this.setRow(this.getMultiRows(folderIdxInternal).size(), creatingRow);
            this.setCurrentRowIdx(this.getMultiRows(folderIdxInternal).size() - 1);
            this.setEditingRow(true);
            this.startAddingDomainSpecificRow(creatingRow);
            return forward;
        } else {
            return lastForward;
        }
    }

    public abstract SimpleMaintMultiRow startAddingDomainSpecificRow(SimpleMaintMultiRow row);

    protected ActionForward finishEditingRow(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, ActionForward forward) {
        if (this.getFolderIdxAsIntInternal() < 0) return forward;
        if (this.getLastPageEvent().startsWith(SimpleMaintMultiRowAction.ACTION_ADDING)) {
            return this.finishAddingRow(mapping, formIn, request, response, errors, forward);
        } else if (this.getLastPageEvent().startsWith(SimpleMaintMultiRowAction.ACTION_UPDATING)) {
            return this.finishUpdatingRow(mapping, formIn, request, response, errors, forward);
        } else {
            return forward;
        }
    }

    public ActionForward startUpdatingRow(ActionMapping mapping, ActionForm formIn, 
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, ActionForward forward) {
        ActionForward lastForward = this.finishEditingRow(mapping, formIn, request, response, errors, forward);
        if (errors.size() == 0) {
            this.setEditingRow(true);
            this.setCurrentRowIdx(this.getPageEventSrcAsInt());
            SimpleMaintMultiRow currentRow = this.getCurrentRow();
            this.setOrignalMultiRow(currentRow.makeCopy());
            currentRow.setRowModeModify();
            return forward;
        } else {
            return lastForward;
        }
    }

    protected MultiRowValidator getCurrentMultiRowValidator() {
        return this.getMulitRowValidators()[this.getFolderIdxAsIntInternal()];
    }

    protected abstract MultiRowValidator[] getMulitRowValidators();

    public ActionForward finishAddingRow(ActionMapping mapping, ActionForm formIn,
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, ActionForward forward) {
        this.getCurrentMultiRowValidator().validateMultiRow(errors);
        if (errors.size() == 0) {
            this.getCurrentRow().setRowModeCreate();
            this.setEditingRow(false);
        } else {
            this.setPageEvent(this.getLastPageEvent());
        }
        return forward;
    }

    public ActionForward finishUpdatingRow(ActionMapping mapping, ActionForm formIn,
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, ActionForward forward) {
        this.getCurrentMultiRowValidator().validateMultiRow(errors);
        if (errors.size() == 0) {
            this.setEditingRow(false);
            this.removeOriginalMultiRow();
        } else {
            this.setPageEvent(this.getLastPageEvent());
        }
        return forward;
    }

    public void deleteCurrentRow() {
        this.getCurrentRow().markAsDeleted(this);
        this.setEditingRow(false);
    }

    protected abstract String[] getLastPageEvents();

    public TableSchema getCurrentChildTs() {
        return this.getChildTs()[this.getFolderIdxAsIntInternal()];
    }

    public String getLastPageEvent() {
        return this.getLastPageEvents()[this.getFolderIdxAsIntInternal()];
    }

    public void setLastPageEvent(String lastPageEvent) {
        if (this.getFolderIdxAsIntInternal() < 0) return; // Handling for the Header Folder
        this.getLastPageEvents()[this.getFolderIdxAsIntInternal()] = lastPageEvent;
    }

    public RemarkTextPopup setRemarkTextPopupValues(RemarkTextPopup popup) {
        // Do nothing by default
        return popup;
    }

    public void retrieveRemarkTextPopupValues(RemarkTextPopup popup) {
        // Do nothing by default
    }

    public abstract SimpleBasePk makePk(String companyCode);

    public ActionForward cancelAddingRow(ActionMapping mapping, ActionForm formIn,
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, ActionForward forward) {
        final int folderIdxInternal = this.getFolderIdxAsIntInternal();
        List rows = this.getMultiRows(folderIdxInternal);
        rows.remove(rows.size() - 1);
        this.setEditingRow(false);
        return forward;
    }

    public ActionForward cancelUpdatingRow(ActionMapping mapping, ActionForm formIn,
            HttpServletRequest request, HttpServletResponse response, ActionErrors errors, ActionForward forward) {
        SimpleMaintMultiRow originalRow = this.removeOriginalMultiRow();
        this.setCurrIdx(this.getFolderIdxAsIntInternal());
        this.setRow(Integer.parseInt(originalRow.getIdx()), originalRow);
        this.setEditingRow(false);
        return forward;
    }

    protected SimpleMaintMultiRow getOriginalMultiRow() {
        return this.originalRow[this.getFolderIdxAsIntInternal()];
    }

    protected void setOrignalMultiRow(SimpleMaintMultiRow originalRow) {
        this.originalRow[this.getFolderIdxAsIntInternal()] = originalRow;
    }

    protected SimpleMaintMultiRow removeOriginalMultiRow() {
        SimpleMaintMultiRow originalMultiRow = this.getOriginalMultiRow();
        this.setOrignalMultiRow(null);
        return originalMultiRow;
    }

}
